package org.redmagic.api;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.redmagic.parse.DefaultMagicParser;

public class Magic implements Location {

    private final Object lock = new Object();
    private final List<Location> locations;
    private final Map<String, String> cache;
    private final boolean ignoreUnresolvablePlaceholders;
    
    public Magic(String magicConfigFile, List<String> localPropertiesOverride) {
        this(magicConfigFile, localPropertiesOverride, false, new DefaultMagicParser());
    }
    
    public Magic(String magicConfigFile, List<String> localPropertiesOverride, boolean ignoreUnresolvablePlaceholders, MagicParser magicParser) {
        this.locations = magicParser.parse(magicConfigFile, localPropertiesOverride);
        this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
        this.cache = new HashMap<String, String>();
    }
    
    public String resolve(String placeholder) {
        synchronized (lock) {
            String result = resolvePlaceholder(placeholder);
            if (shouldFailOnUnresolvedPlaceholder(result)) {
                throw new RuntimeException("Unable to resolve placeholder: " + placeholder);
            } else {
                this.cache.put(placeholder, result);
                return result;
            }            
        }
    }

    private String resolvePlaceholder(String placeholder) {
        String result = null;
        if (this.cache.containsKey(placeholder)) {
            result = this.cache.get(placeholder);
        } else {
            result = checkLocations(placeholder);
        }
        return result;
    }

    private String checkLocations(String placeholder) {
        String result = null;
        for (Location location : locations) {
            result = location.resolve(placeholder);
            if (result != null) {
                break;
            }
        }
        return result;
    }
    
    private boolean shouldFailOnUnresolvedPlaceholder(String result) {
        return result == null && !ignoreUnresolvablePlaceholders;
    }
}